package github.sf.fw.tools.http;

import com.google.gson.*;
import okhttp3.*;
import okhttp3.internal.http.HttpMethod;

import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.Objects;

public class Requests {
    public static final String ContentType = "Content-Type";
    public static final String Application_Json = "application/json; charset=UTF-8";

    public static final String Application_Form = "application/x-www-form-urlencoded; charset=UTF-8";

    public static URL getURL(String url) {
        try {
            return URI.create(url).toURL();
        } catch (MalformedURLException e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] toBytes(Response response) {
        if (response != null && response.body() != null) {
            try {
                return response.body().bytes();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        return null;
    }

    public static String string(Response response) {
        byte[] bytes = toBytes(response);
        if (bytes != null) {
            return new String(bytes, StandardCharsets.UTF_8);
        }
        return null;
    }

    public static String string(Response response, Charset charset) {
        byte[] bytes = toBytes(response);
        if (bytes != null) {
            return new String(bytes, charset);
        }
        return null;
    }

    /**
     * @param fullAddress 完成的url
     */
    public static String unlessPath(String fullAddress) {
        URL urlObj = getURL(fullAddress);
        return urlObj.getProtocol() + "//" + urlObj.getHost() + ":" + urlObj.getPort();
    }

    public Response jsonRequest(String method, URL url, JsonObject jsonObject) {
        return jsonRequest(method, url, null, jsonObject);
    }

    /**
     * 使用json进行传递
     *
     * @param method     方法
     * @param url        url
     * @param headers    请求头
     * @param jsonObject 请求体
     */
    public Response jsonRequest(String method, URL url, Map<String, Object> headers, JsonObject jsonObject) {
        Gson gson = new GsonBuilder().create();
        return request(method, url, headers, MediaType.parse(Application_Json), gson.toJson(jsonObject));
    }

    public Response formRequest(String method, URL url, Map<String, Object> headers, JsonObject jsonObject) {
        return request(method, url, headers, MediaType.parse(Application_Form), toFormData(jsonObject));
    }

    /**
     * 最基本的请求方法
     *
     * @param method    http方法
     * @param url       地址
     * @param headers   请求头
     * @param mediaType 类型
     * @param content   类容
     * @return 响应
     */
    public Response request(String method, URL url, Map<String, Object> headers, MediaType mediaType, String content) {
        SSLSocketFactory sslSocketFactory = SSLSocketClient.getSSLSocketFactory();
//        X509TrustManager x509TrustManager = Platform.get().trustManager(sslSocketFactory);
//        Objects.requireNonNull(x509TrustManager, "TrustManager can't be null");
        OkHttpClient client = new OkHttpClient.Builder()
            .sslSocketFactory(sslSocketFactory, SSLSocketClient.getX509TrustManager())
            .hostnameVerifier(SSLSocketClient.getHostnameVerifier())
            .build();
//        client.setSslSocketFactory(SSLSocketClient.getSSLSocketFactory());
//        client.setHostnameVerifier(SSLSocketClient.getHostnameVerifier());
        //构建请求
        Request.Builder requestBuilder = new Request.Builder();
        requestBuilder.url(url);
        RequestBody requestBody;
        if (!HttpMethod.requiresRequestBody(method) || mediaType == null) {
            requestBody = null;
        } else {
            requestBody = RequestBody.create(mediaType, content);
        }
        requestBuilder.method(method, requestBody);
        if (headers != null && !headers.isEmpty()) {
            headers.forEach((k, v) -> {
                if (!ContentType.equalsIgnoreCase(k)) {
                    requestBuilder.addHeader(k, String.valueOf(v));
                }
            });
        }
        try {
            return client.newCall(requestBuilder.build()).execute();
        } catch (IOException e) {
            throw new RuntimeException("请求异常", e);
        }
    }

    public Response post(URL url, JsonObject jsonObject) {
        Objects.requireNonNull(jsonObject);
        return jsonRequest("POST", url, null, jsonObject);
    }

    public Response put(URL url, JsonObject jsonObject) {
        Objects.requireNonNull(jsonObject);
        return jsonRequest("PUT", url, null, jsonObject);
    }

    public Response delete(URL url, JsonObject jsonObject) {
        Objects.requireNonNull(jsonObject);
        return jsonRequest("DELETE", url, null, jsonObject);
    }

    public Response postForm(URL url, JsonObject jsonObject) {
        String formData = toFormData(jsonObject);
        return request("POST", url, null, MediaType.parse(Application_Form), formData);
    }

    public Response get(URL url, Map<String, Object> headers) {
        return request("GET", url, headers, null, null);
    }

    public String toFormData(JsonObject jsonObject) {
        return toFormData(jsonObject, true);
    }

    public String toFormData(JsonObject jsonObject, boolean encode) {
        if (jsonObject == null) {
            return "";
        }
        StringBuilder formData = new StringBuilder();
        for (String key : jsonObject.keySet()) {
            JsonElement jsonElement = jsonObject.get(key);
            if (jsonElement.isJsonPrimitive()) {
                JsonPrimitive jsonPrimitive = jsonElement.getAsJsonPrimitive();
                String value = jsonPrimitive.getAsString();
                if (encode) {
                    value = getURLEncode(value);
                }
//                value = getURLEncode(value);
                formData.append(key).append("=").append(value).append("&");
            } else {
                String s = jsonElement.toString();
                formData.append(key).append("=").append(s).append("&");
            }
        }
        if (formData.length() > 0) {
            formData.deleteCharAt(formData.length() - 1);
        }
        return formData.toString();
    }

    public String getURLEncode(String content) {
        try {
            return URLEncoder.encode(content, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
    }

    public JsonObject toJsonObj(Response response) {
        String string = string(response);
        if (string == null) {
            return null;
        }
        Gson gson = new GsonBuilder().create();
        return gson.fromJson(string, JsonObject.class);
    }
}
